/** * Copyright (C) 2010-2013 Eugen Feller, INRIA <eugen.feller@inria.fr> * * This file is part of Snooze, a scalable, autonomic, and * energy-aware virtual machine (VM) management framework. * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses>. */ package org.inria.myriads.snoozenode.main; import java.io.FileNotFoundException; import java.io.IOException; import java.net.BindException; import java.net.SocketException; import org.inria.myriads.snoozecommon.communication.NodeRole; import org.inria.myriads.snoozecommon.guard.Guard; import org.inria.myriads.snoozecommon.util.ErrorUtils; import org.inria.myriads.snoozecommon.util.LoggerUtils; import org.inria.myriads.snoozenode.bootstrap.BootstrapBackend; import org.inria.myriads.snoozenode.configurator.NodeConfiguratorFactory; import org.inria.myriads.snoozenode.configurator.api.NodeConfiguration; import org.inria.myriads.snoozenode.configurator.api.NodeConfigurator; import org.inria.myriads.snoozenode.configurator.httpd.HTTPdSettings; import org.inria.myriads.snoozenode.exception.ConnectorException; import org.inria.myriads.snoozenode.exception.HostMonitoringException; import org.inria.myriads.snoozenode.exception.NodeConfiguratorException; import org.inria.myriads.snoozenode.exception.VirtualMachineMonitoringException; import org.inria.myriads.snoozenode.groupmanager.GroupManagerBackend; import org.inria.myriads.snoozenode.localcontroller.LocalControllerBackend; import org.inria.myriads.snoozenode.main.applications.BootstrapApplication; import org.inria.myriads.snoozenode.main.applications.GroupManagerApplication; import org.inria.myriads.snoozenode.main.applications.LocalControllerApplication; import org.inria.myriads.snoozenode.util.OutputUtils; import org.restlet.Application; import org.restlet.Component; import org.restlet.Context; import org.restlet.Server; import org.restlet.data.Protocol; import org.restlet.engine.Engine; import org.restlet.ext.httpclient.HttpClientHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Main node class. * * @author Eugen Feller */ public final class Main { /** Define the logger. */ private static final Logger log_ = LoggerFactory.getLogger(Main.class); /** Number of arguments. */ private static final int NUMBER_OF_CMD_ARGUMENTS = 2; /** Hide constructor. */ private Main() { throw new UnsupportedOperationException(); } /** * Main method. * * @param args The arguments */ public static void main(String[] args) { String configurationFile = null; String logFile = null; if (args.length == NUMBER_OF_CMD_ARGUMENTS) { configurationFile = args[0]; logFile = args[1]; } else { System.out.println("Usage: java -jar snoozenode.jar configurationFile logFile"); System.exit(1); } LoggerUtils.configureLogger(logFile); NodeConfiguration nodeConfiguration = null; try { NodeConfigurator nodeConfigurator = NodeConfiguratorFactory.newNodeConfigurator(configurationFile); nodeConfiguration = nodeConfigurator.getNodeConfiguration(); OutputUtils.printNodeConfiguration(nodeConfiguration); startNode(nodeConfiguration); log_.info(String.format("%s started successfully!", nodeConfiguration.getNode().getRole())); } catch (NodeConfiguratorException exception) { ErrorUtils.processError(String.format("Node configuration exception! Error during node " + "configuration parsing: %s", exception.getMessage())); } catch (IllegalArgumentException exception) { ErrorUtils.processError(String.format("Illegal argument exception! Check your configuration file: %s", ErrorUtils.getStackTrace(exception))); } catch (BindException exception) { ErrorUtils.processError(String.format("Bind exception: %s", exception.getMessage())); } catch (FileNotFoundException exception) { ErrorUtils.processError(String.format("Configuration file does not exist: %s", exception.getMessage())); } catch (ConnectorException exception) { ErrorUtils.processError(String.format("Something critical happened during hypervisor connection: %s", exception.getMessage())); } catch (VirtualMachineMonitoringException exception) { ErrorUtils.processError(String.format("Something critical happened during monitoring: %s", exception.getMessage())); } catch (SocketException exception) { ErrorUtils.processError(String.format("Socket exception: %s! Are you sure network is available?", exception.getMessage())); } catch (HostMonitoringException exception) { ErrorUtils.processError(String.format("Something critical happened during host monitoring: %s", exception.getMessage())); } catch (UnsatisfiedLinkError error) { ErrorUtils.processError(String.format("Link error: %s", error.getMessage())); } catch (IOException exception) { ErrorUtils.processError(String.format("I/O exception", ErrorUtils.getStackTrace(exception))); } catch (InterruptedException exception) { ErrorUtils.processError(String.format("Interrupted exception", ErrorUtils.getStackTrace(exception))); } catch (Exception exception) { log_.error("Exception", exception); } } /** * Initializes the component. * * @param component The component * @param context The context * @param configuration The node parameters * @throws Exception */ private static void initializeRESTletComponent(Component component, Context context, NodeConfiguration configuration) throws Exception { Guard.check(component, context, configuration); log_.debug("Initializing the RESTlet component"); Engine.getInstance().getRegisteredClients().clear(); Engine.getInstance().getRegisteredClients().add(new HttpClientHelper(null)); component.getClients().add(Protocol.HTTP); Server jettyServer = new Server(context, Protocol.HTTP, configuration.getNetworking().getListen().getControlDataAddress().getPort(), component); HTTPdSettings settings = configuration.getHTTPd(); jettyServer.getContext().getParameters().add("maxThreads", settings.getMaximumNumberOfThreads()); jettyServer.getContext().getParameters().add("maxTotalConnections", settings.getMaximumNumberOfConnections()); jettyServer.getContext().getParameters().add("maxThreads", settings.getMaximumNumberOfThreads()); jettyServer.getContext().getParameters().add("maxTotalConnections", settings.getMaximumNumberOfConnections()); jettyServer.getContext().getParameters().add("minThreads", settings.getMinThreads()); jettyServer.getContext().getParameters().add("lowThreads", settings.getLowThreads()); jettyServer.getContext().getParameters().add("maxThreads", settings.getMaxThreads()); jettyServer.getContext().getParameters().add("maxQueued", settings.getMaxQueued()); jettyServer.getContext().getParameters().add("maxIoIdleTimeMs", settings.getMaxIoIdleTimeMs()); component.getServers().add(jettyServer); } /** * Main routine to start the node. * * @param nodeConfiguration The node configuration * @throws Exception */ private static void startNode(NodeConfiguration nodeConfiguration) throws Exception { Guard.check(nodeConfiguration); log_.debug("Starting the node initialization"); Component component = new Component(); Context context = component.getContext().createChildContext(); initializeRESTletComponent(component, context, nodeConfiguration); Application application = null; NodeRole nodeRole = nodeConfiguration.getNode().getRole(); switch (nodeRole) { case bootstrap : log_.debug("Starting in bootstap mode"); application = new BootstrapApplication(context); attachApplication(component, application); BootstrapBackend bootstrap = new BootstrapBackend(nodeConfiguration); context.getAttributes().put("backend", bootstrap); break; case groupmanager : log_.debug("Starting in group manager mode"); application = new GroupManagerApplication(context); attachApplication(component, application); GroupManagerBackend groupmanager = new GroupManagerBackend(nodeConfiguration); context.getAttributes().put("backend", groupmanager); break; case localcontroller : log_.debug("Starting in local controller mode"); application = new LocalControllerApplication(context); attachApplication(component, application); LocalControllerBackend localcontroller = new LocalControllerBackend(nodeConfiguration); context.getAttributes().put("backend", localcontroller); break; default: log_.error(String.format("This node role is not supported: %s", nodeRole)); } } /** * Attaches the application to RESTlet component. * * @param component The component * @param application The application * @throws Exception The exception */ private static void attachApplication(Component component, Application application) throws Exception { Guard.check(component, application); log_.debug("Attaching application to the RESTlet component"); component.getDefaultHost().attach(application); component.start(); log_.debug("RESTlet component started!"); } }